package me.kagami.fup;

import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import me.kagami.fup.excel.ExportData;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class ResultCollector {
    public static String NOT_ASSIGN = "Set方法未被调用";
    public static String BIGGER_5 = "set调用处大于5处";

    private Project project;
    private List<ResultBean> resultBeans = new ArrayList<>();

    public ResultCollector(Project project) {
        this.project = project;
    }

    public void collect(PsiField psiField, PsiElement psiElement, List<PsiMethod> cycleCollection, String message, PsiElement showElement) {
        String key = getKey(psiElement.getContainingFile(), psiElement.getTextRange());
        for (ResultBean resultBean : resultBeans) {
            if (resultBean.getKey().equals(key)) {
                System.out.println("key已经存在:" + key);
                resultBean.setField(psiField);
                resultBean.setCallChain(cycleCollection);
                resultBean.setMessage(message);
                resultBean.setPsiElement(showElement);
                return;
            }
        }
        ResultBean resultBean = new ResultBean();
        resultBean.setKey(key);
        resultBean.setField(psiField);
        resultBean.setCallChain(cycleCollection);
        resultBean.setMessage(message);
        resultBean.setPsiElement(showElement);
        resultBeans.add(resultBean);


    }

    public void collect(PsiField psiField, PsiMethod psiMethod, List<PsiMethod> cycleCollection, PsiElement showElement) {
        String key = getKey(psiMethod.getContainingFile(), psiMethod.getTextRange());
        for (ResultBean resultBean : resultBeans) {
            if (resultBean.getKey().equals(key)) {
                System.out.println("key已经存在:" + key);
                resultBean.setField(psiField);
                resultBean.setCallChain(cycleCollection);
                resultBean.setMessage(key);
                resultBean.setPsiElement(showElement);
                return;
            }
        }
        ResultBean resultBean = new ResultBean();
        resultBean.setKey(key);
        resultBean.setField(psiField);
        resultBean.setCallChain(cycleCollection);
        resultBean.setPsiElement(showElement);
        resultBean.setMessage(key + " - Method:" + psiMethod.getName());
        resultBeans.add(resultBean);

    }

    public void collect(PsiField psiField, String message, PsiElement showElement) {
        String key = getKey(psiField.getContainingFile(), psiField.getTextRange());
        for (ResultBean resultBean : resultBeans) {
            if (resultBean.getKey().equals(key)) {
                System.out.println("key已经存在:" + key);
                resultBean.setField(psiField);
                resultBean.setMessage(message);
                resultBean.setPsiElement(showElement);
                return;
            }
        }
        ResultBean resultBean = new ResultBean();
        resultBean.setKey(key);
        resultBean.setField(psiField);
        resultBean.setMessage(message);
        resultBean.setPsiElement(showElement);
        resultBeans.add(resultBean);
    }

    @NotNull
    private String getKey(PsiFile psiField, TextRange textRange) {
        PsiFile containingFile = psiField;
        Document document = PsiDocumentManager.getInstance(project).getDocument(containingFile);
        int lineNumber = document.getLineNumber(textRange.getStartOffset());
        String key = "File:" + containingFile.getName() + " - Line:" + lineNumber;
        return key;
    }

    public void printSelf() {
        for (ResultBean resultBean : resultBeans) {
            System.out.println(resultBean);
        }
    }

    public List<ResultBean> getResultBeans() {
        return resultBeans;
    }


    public List<ExportData> toExportDataList() {
        List<ExportData> result = new ArrayList<>();
        for (ResultBean resultBean : resultBeans) {
            ExportData exportData = new ExportData();
            exportData.setEndFile(resultBean.getKey());
            exportData.setField(resultBean.getFieldStr());
            exportData.setCallChain(resultBean.getChainStr());
            exportData.setMessage(resultBean.getMessage());
            result.add(exportData);
        }
        return result;
    }

    public class ResultBean {
        private String key;
        private PsiField field;
        private List<PsiMethod> callChain;
        private PsiElement psiElement;
        private String message;

        public PsiField getField() {
            return field;
        }

        public void setField(PsiField field) {
            this.field = field;
        }

        public List<PsiMethod> getCallChain() {
            return callChain;
        }

        public void setCallChain(List<PsiMethod> callChain) {
            this.callChain = (List<PsiMethod>) ((ArrayList) callChain).clone();
        }

        public String getMessage() {
            return message;
        }

        public void setMessage(String message) {
            this.message = message;
        }

        public String getKey() {
            return key;
        }

        public void setKey(String key) {
            this.key = key;
        }

        @Override
        public String toString() {

            return "key='" + key + '\'' + ", field='" + getFieldStr() + '\'' + ", callChain=" + getChainStr() + ", message='" + message + '\'';
        }

        @NotNull
        private String getFieldStr() {
            Document document = PsiDocumentManager.getInstance(project).getDocument(field.getContainingFile());
            int lineNumber = document.getLineNumber(field.getTextRange().getStartOffset());
            String fsb = "[File:" + field.getContainingFile().getName() + " - Line:" + lineNumber + " - Name:" + field.getName() + "]";
            return fsb;
        }

        @NotNull
        private String getChainStr() {
            StringBuilder sb = new StringBuilder();
            if (callChain == null || callChain.size() == 0) {
                sb.append("[],");
            } else {
                for (PsiMethod psiMethod : callChain) {
                    Document document = PsiDocumentManager.getInstance(project).getDocument(psiMethod.getContainingFile());
                    int lineNumber = document.getLineNumber(psiMethod.getTextRange().getStartOffset());
                    String key = "[File:" + psiMethod.getContainingFile().getName() + " - Line:" + lineNumber + " - Method:" + psiMethod.getName() + "],";
                    sb.append(key);
                }
            }
            return sb.substring(0, sb.length() - 1);
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            ResultBean that = (ResultBean) o;
            return Objects.equals(key, that.key);
        }

        @Override
        public int hashCode() {
            return Objects.hash(key);
        }

        public PsiElement getPsiElement() {
            return psiElement;
        }

        public void setPsiElement(PsiElement psiElement) {
            this.psiElement = psiElement;
        }
    }

}
